#! /usr/bin/python

import curses, os, sys
from xml.dom import minidom, Node

#
# Configuration must reside in ~/.sshbookrc and be on
# The following format:
#
#<sshbook>
#	<host name="foo" user="l337"/>
#	<host name="bar"/>
#</sshbook>
#

class SSHBookConfig:

	host = None
	uname = None
	focused = False		# Used when displaying the list in the interface

	def __init__(self, host, uname=None):
		self.host  = host
		self.uname = uname

	def __str__(self):
		if self.uname:
			return self.uname + '@' + self.host
		else:
			return self.host


class SSHBook:

	__inter_height = 10
	__inter_width  = 80

	def showlist(self, hostlist):
		""" Prints the contents of the supplied hostlist in
		    specified window.
		"""
		(maxY, maxX) = self.stdscr.getmaxyx()

		xoff = int ((maxX - self.__inter_width) / 4)
		yoff = int ((maxY - self.__inter_height) / 2)

		self.stdscr.clear()

		for x in hostlist:
			if x.focused:
				self.stdscr.addstr(yoff, xoff, str(x), curses.A_REVERSE)
			else:
				self.stdscr.addstr(yoff, xoff, str(x))
			yoff += 1

		for x in range(3):
			self.stdscr.addstr(yoff, xoff, '')
			yoff += 1

		self.stdscr.refresh()


	def getselection(self,  hostlist):
		""" Performs all actions needed to get input from the
		    the user: Print the list, read in result from selection
		    and returning if to the callee.
		"""
		# Show the list to the user.
		focus = 0
		hostlist[focus].focused = True

		while True:
			# Set the focus and print the list.
			self.showlist(hostlist)

			# Get user input.
			c = self.stdscr.getch()

			# Descide which action (if any) to take.
			if c == curses.KEY_DOWN:	# Move down in the host list
				if focus < len(hostlist)-1:
					hostlist[focus].focused = False
					focus += 1
					hostlist[focus].focused = True
					
			elif c == curses.KEY_UP:	# Move up in the host list
				if focus > 0:
					hostlist[focus].focused = False
					focus -= 1
					hostlist[focus].focused = True
			elif c == curses.KEY_ENTER or c == 10:	# Got selection.
				return hostlist[focus]
			elif c == ord('q'):			# Exit the application
				return False



	def parseconfig(self):
		""" Parses the configuration file and returns a
		    list of configuration objects.
		"""

		hostlist = []

		# The location of the configuration file.
		try:
			rcfile = os.getenv('HOME')
			if rcfile:
				rcfile += '/.sshbookrc'
			else:
				print 'Failed retreive HOME from environment'
				sys.exit(1)
		except OSError, (errno, strerror):
			print strerror
			sys.exit(1)

		# Parse the contents using a DOM XML parser.
		conf = minidom.parse(rcfile)
		root = conf.documentElement

		if root.nodeType == Node.ELEMENT_NODE and root.nodeName == 'sshbook':
			for child in root.childNodes:
				host = None
				user = None

				if child.nodeType == Node.ELEMENT_NODE and child.nodeName == 'host':
					attrs = child.attributes

					for x in attrs.keys():
						if x == 'name':
							host = attrs.get('name').value
						elif x == 'user':
							user = attrs.get('user').value
					if host:
						hostlist.append(SSHBookConfig(host,user))
		return hostlist


	def main(self):
		""" Sets up and run the application. """
		# Read configuration
		hostlist = self.parseconfig()

		if hostlist:
			# Start up the curses environment.
			self.stdscr = curses.initscr()
			curses.noecho()		# Don't echo keys
			curses.cbreak()		# Don't require ENTER
			self.stdscr.keypad(1)	# Get escape codes as nice named constants


			# Get the user selection.
			if self.stdscr:
				selection = self.getselection(hostlist)
			else:
				selection = False

			# Shutdown the curses environment.
			curses.nocbreak()
			self.stdscr.keypad(0)
			curses.echo()

			self.stdscr.clear()
			self.stdscr.refresh()
			curses.endwin()

			# Validate input and exec() into the new SSH session.
			if self.stdscr and selection:
				print str(selection)

			#apa = ('ssh', (str(selection)))
			#print apa
				try:
					os.execvp('ssh', ('ssh', str(selection)))
				except OSError, (errno, strerror):
					print strerror
					print 'Tried to use ' + str(selection) + ' as parameter to ssh'

		# Ask the user to provide some configuration
		else:
			print 'Found no configuration. Exiting'





if __name__ == '__main__':
	SSHBook().main()